package com.fulihui.usercore.service;

import com.fulihui.usercore.api.UserAddressService;
import com.fulihui.usercore.common.util.Errors;
import com.fulihui.usercore.condition.UserAddressCondition;
import com.fulihui.usercore.core.repository.UserAddressRepository;
import com.fulihui.usercore.dto.UserAddressDTO;
import com.fulihui.usercore.request.address.UserAddressSaveRequest;
import com.fulihui.usercore.request.address.UserAddressSingleRequest;
import org.apache.dubbo.config.annotation.Service;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.servicesupport.request.TRequest;
import org.near.servicesupport.result.BaseResult;
import org.near.servicesupport.result.ResultBuilder;
import org.near.servicesupport.result.TMultiResult;
import org.near.servicesupport.result.TSingleResult;
import org.near.servicesupport.util.ServiceAssert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static org.near.servicesupport.error.Errors.Commons.REQUEST_PARAMETER_ERROR;

/**
 * @author Willard.Hu on 2016/5/17.
 */
@Service(version = "1.0.0")
public class UserAddressServiceImpl implements UserAddressService {
    @Autowired
    private UserAddressRepository userAddressRepository;

    @Value("${user.address.limit:10}")
    private int userAddressLimit;

    @Override
    @Transactional
    public TSingleResult<UserAddressDTO> save(UserAddressSaveRequest request) {
        if (request.isDefaultAddr()) {
            List<UserAddressDTO> usrAddrList = userAddressRepository.queryByUser(request.getUserId());
            boolean b = userAddressRepository.cancelUserAddrDefault(request.getUserId());
            // 数据库中有地址列表，但更新失败
            if (!b && !CollectionUtils.isEmpty(usrAddrList)) {
                return ResultBuilder.failTSingle(Errors.UserAddress.SAVE_FAILED);
            }
        }
        UserAddressDTO save = new UserAddressDTO();
        BeanUtils.copyProperties(request, save);
        long id;
        if ((id = request.getId()) > 0) { // update，
            boolean b = userAddressRepository.update(save);
            if (!b) {
                return ResultBuilder.failTSingle(Errors.UserAddress.SAVE_FAILED);
            }
        } else { // create
            List<UserAddressDTO> addrs = userAddressRepository.queryByUser(request.getUserId());
            if (addrs != null && addrs.size() >= userAddressLimit) {
                throw new InvokeServiceException(Errors.UserAddress.ADDRESS_SIZE_OVER_LIMIT);
            }
            id = userAddressRepository.create(save);
        }
        UserAddressDTO newaddr = userAddressRepository.queryByPK(id, request.getUserId());
        return ResultBuilder.succTSingle(newaddr);
    }

    @Override
    public BaseResult delete(UserAddressSingleRequest request) {
        ServiceAssert.notBlank(request.getUserId(), REQUEST_PARAMETER_ERROR);
        boolean b = userAddressRepository.delete(request.getId(), request.getUserId());
        if (!b) {
            return ResultBuilder.fail(BaseResult.class, Errors.UserAddress.DEL_FAILED);
        }
        return ResultBuilder.succ(BaseResult.class);
    }

    @Override
    public TSingleResult<UserAddressDTO> queryByPK(UserAddressSingleRequest request) {
        ServiceAssert.notBlank(request.getUserId(), REQUEST_PARAMETER_ERROR);
        UserAddressDTO userAddress = userAddressRepository.queryByPK(request.getId(),
                request.getUserId());
        return ResultBuilder.succTSingle(userAddress);
    }

    @Override
    public TMultiResult<UserAddressDTO> queryByUser(TRequest<UserAddressCondition> request) {
        UserAddressCondition condition = request.getCondition();
        ServiceAssert.notNull(condition, REQUEST_PARAMETER_ERROR);
        ServiceAssert.notBlank(condition.getUserId(),
                REQUEST_PARAMETER_ERROR);
        List<UserAddressDTO> usrAddrList = userAddressRepository.queryByUser(condition.getUserId());
        if (condition.isNeedDefault() && !CollectionUtils.isEmpty(usrAddrList)) {
            Optional<UserAddressDTO> opt = usrAddrList.stream()
                    .filter(UserAddressDTO::isDefaultAddr).findFirst();
            usrAddrList = opt.map(Collections::singletonList).orElseGet(Collections::emptyList);
        }
        return ResultBuilder.succTMulti(usrAddrList);
    }
}
